cleanupを使ってuseEffectのネットワークのRace Conditionを避ける
code:ts
export default function Page() {
useEffect(() => {
let ignore = false;
setBio(null);
fetchBio(person).then(result => {
if (!ignore) {
setBio(result);
}
});
return () => {
ignore = true;
};
ignore変数を使ってrace conditionにならないようにしている
通信のresponseの順序は、requestの順序と異なる可能性がある
2回目のfetchのresponseが、1回目より先に返ってくると、
2回目の結果を、古い1回目の結果が上書きしてしまう
ignoreがあることで、
1回目の完了前に、2回目が始まるときに、
1回目のrenderingに着目すると、
1回目の完了前に次のrenderingが始まるので、
cleanupが実行され、
ignoreがtrueになるので、
1回目のsetBioの更新は実行されない
code:ts
export default function Page() {
useEffect(() => {
const abortController = new AbortController();
const fetchData = async () => {
setBio(null);
try {
const result = await fetchBio(person, { signal: abortController.signal });
setBio(result);
} catch (error) {
if (error.name === 'AbortError') {
// リクエストが中止された場合の処理
console.log('Fetch aborted');
} else {
// 他のエラーの処理
console.error('Fetch error:', error);
}
}
};
fetchData();
return () => {
abortController.abort();
};
race conditionが起こっている例
https://gyazo.com/b8b11dd14f451aee19564bf70ccc3894
~00:10まではゆっくり操作している場合の正常な例
チェックボックスをゆっくりクリックすれば、内容が切り替わる
わかりにくいが、00:10~らへんで、素早く2つのチェックボックスをクリックしている
「絵本・児童書」→「アートデザイン・音楽」の順にクリックしている
理想的には、その2つがチェック済みになるはずだが、
1回目のresponseが返ってくる前に、回目のクリックによるrequestをすることで結果が上書きされ、
1回目のクリックが無視されている